import * as vscode from 'vscode';
import { DeviceConnectionManager, ConnectionState } from './deviceConnectionManager';

export class ReplTerminal implements vscode.Pseudoterminal {
    private writeEmitter = new vscode.EventEmitter<string>();
    private closeEmitter = new vscode.EventEmitter<number>();
    private connectionManager: DeviceConnectionManager;
    private buffer: string = '';

    onDidWrite: vscode.Event<string> = this.writeEmitter.event;
    onDidClose: vscode.Event<number> = this.closeEmitter.event;

    constructor(connectionManager: DeviceConnectionManager) {
        this.connectionManager = connectionManager;

        // Listen for data from the device
        this.connectionManager.onDataReceived((data) => {
            this.writeEmitter.fire(data);
        });

        // Listen for connection state changes
        this.connectionManager.onStateChange((state) => {
            if (state === ConnectionState.CONNECTED) {
                this.writeEmitter.fire('\r\n✓ Connected to MicroPython device\r\n');
                this.writeEmitter.fire('>>> ');
            } else if (state === ConnectionState.DISCONNECTED) {
                this.writeEmitter.fire('\r\n✗ Disconnected from device\r\n');
            } else if (state === ConnectionState.ERROR) {
                this.writeEmitter.fire('\r\n✗ Connection error\r\n');
            }
        });
    }

    open(initialDimensions: vscode.TerminalDimensions | undefined): void {
        this.writeEmitter.fire('MicroPython REPL Terminal\r\n');
        this.writeEmitter.fire('========================\r\n');

        if (this.connectionManager.isConnected) {
            this.writeEmitter.fire('✓ Connected to device\r\n');
            this.writeEmitter.fire('>>> ');
        } else {
            this.writeEmitter.fire('✗ No device connected. Use "MicroPython: Connect Device" to connect.\r\n');
        }
    }

    close(): void {
        this.closeEmitter.fire(0);
    }

    handleInput(data: string): void {
        if (!this.connectionManager.isConnected) {
            this.writeEmitter.fire('\r\n✗ Device not connected\r\n');
            return;
        }

        // 直接将所有输入发送到设备，让 MicroPython REPL 处理回显
        // MicroPython 会自动回显字符，我们不需要在本地处理

        if (data === '\r') {
            // Enter key - 发送回车换行
            this.connectionManager.sendRawData(Buffer.from('\r\n'));
            this.buffer = '';
        } else if (data === '\x7f' || data === '\b') {
            // Backspace - 发送退格符
            this.connectionManager.sendRawData(Buffer.from([0x7f]));
            if (this.buffer.length > 0) {
                this.buffer = this.buffer.slice(0, -1);
            }
        } else if (data === '\x03') {
            // Ctrl+C - 发送中断信号
            this.connectionManager.sendRawData(Buffer.from([0x03]));
            this.buffer = '';
        } else if (data === '\x04') {
            // Ctrl+D - 软重启
            this.connectionManager.sendRawData(Buffer.from([0x04]));
            this.buffer = '';
        } else {
            // 所有其他字符直接发送到设备
            this.connectionManager.sendRawData(Buffer.from(data));
            this.buffer += data;
        }
    }

    setDimensions(dimensions: vscode.TerminalDimensions): void {
        // Terminal dimensions changed
    }
}

export class ReplTerminalProvider {
    private connectionManager: DeviceConnectionManager;
    private activeTerminal?: vscode.Terminal;

    constructor(connectionManager: DeviceConnectionManager) {
        this.connectionManager = connectionManager;
    }

    public createReplTerminal(): vscode.Terminal {
        const pty = new ReplTerminal(this.connectionManager);

        this.activeTerminal = vscode.window.createTerminal({
            name: 'MicroPython REPL',
            pty: pty,
            iconPath: new vscode.ThemeIcon('terminal')
        });

        return this.activeTerminal;
    }

    public showReplTerminal(): void {
        if (!this.activeTerminal) {
            this.createReplTerminal();
        }

        this.activeTerminal!.show();
    }

    public dispose(): void {
        if (this.activeTerminal) {
            this.activeTerminal.dispose();
        }
    }
}
